package com.polidea.rxohosble2.sample.example1_scanning;

import com.polidea.rxohosble2.RxBleClient;
import com.polidea.rxohosble2.exceptions.BleScanException;
import com.polidea.rxohosble2.internal.RxBleLog;
import com.polidea.rxohosble2.sample.ResourceTable;
import com.polidea.rxohosble2.sample.SampleApplication;
import com.polidea.rxohosble2.sample.DeviceAbility;
import com.polidea.rxohosble2.sample.example1a_background_scanning.BackgroundScanAbility;
import com.polidea.rxohosble2.sample.util.LocationPermission;
import com.polidea.rxohosble2.sample.util.ScanExceptionHandler;
import com.polidea.rxohosble2.scan.ScanFilter;
import com.polidea.rxohosble2.scan.ScanResult;
import com.polidea.rxohosble2.scan.ScanSettings;
import io.reactivex.ohos.schedulers.OhosSchedulers;
import io.reactivex.disposables.Disposable;
import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
import ohos.aafwk.content.Operation;
import ohos.agp.components.Button;
import ohos.agp.components.Component;
import ohos.agp.components.ListContainer;
import ohos.bundle.IBundleManager;

public class ScanAbility extends Ability {
    private static final int REQUEST_PERMISSION_LOCATION = 100;
    private Button scanToggleButton;
    private ListContainer listContainer;
    private RxBleClient rxBleClient;
    private Disposable scanDisposable;
    private ScanResultsAdapter resultsAdapter;
    private boolean hasClickedScan;

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        setPattern(ResourceTable.Pattern_base);
        super.setUIContent(ResourceTable.Layout_ability_example1);
        requestPermission();
        findComponentById(ResourceTable.Id_background_scan_btn).setClickedListener(this::onBackgroundScanRequested);
        scanToggleButton = (Button) findComponentById(ResourceTable.Id_scan_toggle_btn);
        listContainer = (ListContainer) findComponentById(ResourceTable.Id_scan_results);
        rxBleClient = SampleApplication.getRxBleClient(this);
        scanToggleButton.setClickedListener(this::onScanToggleClick);
        configureResultList();
    }
    //请求权限
    public void requestPermission() {
        if(verifySelfPermission("ohos.permission.LOCATION") != IBundleManager.PERMISSION_GRANTED || verifySelfPermission("ohos.permission.LOCATION_IN_BACKGROUND") != IBundleManager.PERMISSION_GRANTED){
            requestPermissionsFromUser(
                    new String[] { "ohos.permission.LOCATION","ohos.permission.LOCATION_IN_BACKGROUND" } , REQUEST_PERMISSION_LOCATION);
        }
    }


    private void onBackgroundScanRequested(Component component) {
        Intent intent = new Intent();
        Operation operation = new Intent.OperationBuilder()
                .withDeviceId("")
                .withBundleName(getBundleName())
                .withAbilityName(BackgroundScanAbility.class)
                .build();
        intent.setOperation(operation);
        startAbility(intent);
    }

    private void onScanToggleClick(Component component) {

        if (isScanning()) {
            scanDisposable.dispose();
        } else {
            if (rxBleClient.isScanRuntimePermissionGranted()) {
                scanBleDevices();
            } else {
                hasClickedScan = true;
                LocationPermission.requestLocationPermission(this, rxBleClient);
            }
        }

        updateButtonUIState();
    }

    private void scanBleDevices() {
        scanDisposable = rxBleClient.scanBleDevices(
                new ScanSettings.Builder()
                        .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
                        .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
                        .build(),
                new ScanFilter.Builder()
//                            .setDeviceAddress("B4:99:4C:34:DC:8B")
                        // add custom filters if needed
                        .build()
        )
                .observeOn(OhosSchedulers.mainThread())
                .doFinally(this::dispose)
                .subscribe(resultsAdapter::addScanResult, this::onScanFailure);
    }

    @Override
    public void onRequestPermissionsFromUserResult(int requestCode, String[] permissions, int[] grantResults) {
        if (LocationPermission.isRequestLocationPermissionGranted(requestCode, permissions, grantResults, rxBleClient)
                && hasClickedScan) {
            hasClickedScan = false;
            scanBleDevices();
        }
    }

    @Override
    protected void onInactive() {
        super.onInactive();
        if (isScanning()) {
            /*
             * Stop scanning in onPause callback.
             */
            scanDisposable.dispose();
        }
    }

    private void configureResultList() {
        resultsAdapter = new ScanResultsAdapter(new ScanResultsAdapter.OnClickListener() {
            @Override
            public void onclick(int position) {
                final ScanResult itemAtPosition = resultsAdapter.getItemAtPosition(position);
                onAdapterItemClick(itemAtPosition);
            }
        });
        listContainer.setItemProvider(resultsAdapter);
//        listContainer.setItemClickedListener((listContainer, component, i, l) -> {
//            final ScanResult itemAtPosition = resultsAdapter.getItemAtPosition(i);
//            onAdapterItemClick(itemAtPosition);
//        });
    }

    private boolean isScanning() {
        return scanDisposable != null;
    }

    private void onAdapterItemClick(ScanResult scanResults) {
        RxBleLog.i("onAdapterItemClick scanResults:"+scanResults);
        final String macAddress = scanResults.getBleDevice().getMacAddress();
        final Intent intent = new Intent();
        intent.setParam(DeviceAbility.EXTRA_MAC_ADDRESS, macAddress);

        Operation operation = new Intent.OperationBuilder()
                .withDeviceId("")
                .withBundleName(getBundleName())
                .withAbilityName(DeviceAbility.class)
                .build();
        intent.setOperation(operation);
        startAbility(intent);
    }

    private void onScanFailure(Throwable throwable) {
        if (throwable instanceof BleScanException) {
            ScanExceptionHandler.handleException(this,(BleScanException) throwable);
        }
    }

    private void dispose() {
        scanDisposable = null;
        resultsAdapter.clearScanResults();
        updateButtonUIState();
    }

    private void updateButtonUIState() {
        scanToggleButton.setText(isScanning() ? ResourceTable.String_stop_scan : ResourceTable.String_start_scan);
    }
}
